#include "Vector3.h"
#include "Vector2.h"

Vector3::Vector3() :BaseVector(4)
{
	this->Set(0, 0, 0, 1);
}

Vector3::Vector3(double x, double y, double z, double w):BaseVector(4)
{
	this->Set(x, y, z, w);
}

Vector3::Vector3(const Vector3 & v): Vector3(v.GetX(),v.GetY(),v.GetZ(),v.GetW())
{
}

Vector3::Vector3(const Vector2 & v) : Vector3(v.GetX(), v.GetY(), 0, v.GetW())
{
}

Vector3::Vector3(const BaseVector & v):BaseVector(v)
{
}

Vector3::~Vector3()
{
}

void Vector3::Set(double x, double y, double z, double w)
{
	this->SetX(x);
	this->SetY(y);
	this->SetZ(z);
	this->SetW(w);
}

void Vector3::SetX(double x)
{
	this->data[0] = x;
}

void Vector3::SetY(double y)
{
	this->data[1] = y;
}

void Vector3::SetZ(double z)
{
	this->data[2] = z;
}

void Vector3::SetW(double w)
{
	this->data[3] = w;
}

double Vector3::GetX() const
{
	return this->data[0];
}

double Vector3::GetY() const
{
	return this->data[1];
}

double Vector3::GetZ() const
{
	return this->data[2];
}

double Vector3::GetW() const
{
	return this->data[3];
}

Vector3 & Vector3::operator=(const Vector2 & v)
{
	this->SetX(v.GetX());
	this->SetY(v.GetY());
	return *this;
}

Vector3 & Vector3::operator=(const Vector3 & v)
{
	if (this == &v) return *this;
	double* values = v.GetValues();
	this->SetValues(values);
	delete[] values;
	return *this;
}

Vector3 & Vector3::operator=(const BaseVector & v)
{
	if (this == &v) return *this;
	double* values = v.GetValues();
	this->SetValues(values);
	delete[] values;
	return *this;
}

Vector3 Vector3::FromMatrix(Matrix mat)
{
	double* data = mat.GetValues();
	Vector3 res(data[0], data[1], data[2], data[3]);
	delete[] data;
	return res;
}

void Vector3::SetUpOrthogonalBasisByW(Vector3 & u, Vector3 & v, Vector3 & w)
{
	w.Identity();
	double *data = w.GetValues();
	int min = 0;
	for (int i = 1; i < 3; i++)
		if (data[min] > data[i])
			min = i;
	data[min] = 1;
	Vector3 t(data[0], data[1], data[2], data[3]);
	if (t == w)
	{
		data[min] = 2;
		t.SetValues(data);
	}
	u = BaseVector::Identity(CrossProduct(t, w));
	v = CrossProduct(w, u);
	delete[] data;
}
